//
// system timer fired
//
// RFTimerFired.h
//
// wangsihong@live.com
//

#ifndef Rooftop_TimerFired_H
#define Rooftop_TimerFired_H

#include <iostream>
#ifndef Q_MOC_RUN 
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#endif

#include "RFObject.h"
#include "RFEventBase.h"
#include "RFEventManager.h"

namespace Rooftop {
#define RF_TIMERFIRED "timer-fired-event"
#define RF_TIMERFIRED_TIME_MS 0
    class TimerEvent : public EventBase {
        public:
        TimerEvent()
            : EventBase(RF_TIMERFIRED)
        {
        }

        ~TimerEvent()
        {
        }
    };

    template <typename T>
    class Task : public RFObject {
        public:
        Task()
            : m_running(false)
        {
        }
        typedef void (T::*TFunc)(Task *);
        Task(T *obj, TFunc f)
            : m_running(false)
        {
            _cb = boost::bind(f, obj, this);
        }

        bool callback(EventBase &)
        {
            if (m_running && m_connect.connected()) {
                try{
                    _cb();
                } catch (boost::bad_function_call &ex) {
                    fprintf(stderr, "Error %d for %s\n", ex.what(), "task event callback");
                }
            }
            return true;
        }

        void reg()
        {
            m_connect = EventManager::getInstance()->addEventCallback(RF_TIMERFIRED, 
                                                        boost::bind(&Task<T>::callback, this, _1));
            m_running = true;
        }

        void unreg()
        {
            m_running = false;
            m_connect.disconnect();
        }

        void block()
        {
            //m_connect.block();
        }

        void unblock()
        {
            //m_connect.unblock();
        }

        private:
        boost::function<void ()> _cb;
        TimerEvent m_event;
        boost::signals2::connection m_connect;
        bool m_running;
    };

    class SystemTimerFired : public RFObject {
        public:
        static SystemTimerFired* getInstance();
        void fired();
        void start();
        void stop();
        void suspendWK();
        void continueWK();

        void setTimerFiredTimeMS(int ms) {
            if (ms > 0)
                m_timerFiredTimeMS = ms;
        }

        void setFiredTimes(int times) {
            if (times > 0) 
                m_firedTimes = times;
            else
                m_firedTimes = 1;
        }

        private:
        SystemTimerFired()
            : boost_timer(boost_io, boost::posix_time::milliseconds(RF_TIMERFIRED_TIME_MS))
            , m_isRunning(false)
            , m_timerFiredTimeMS(RF_TIMERFIRED_TIME_MS)
            , m_firedTimes(1)
        {
            EventManager::getInstance()->addEventListener(RF_TIMERFIRED);
        }
        static SystemTimerFired *p_instance;
        TimerEvent m_event;
        boost::asio::io_service boost_io;
        boost::asio::deadline_timer boost_timer; 
        bool m_isRunning;
        int m_timerFiredTimeMS;
        int m_firedTimes;
    };
}

#endif

